Conversation
4a7fc18 to
f39ef05
Compare
f39ef05 to
267785b
Compare
| self.remove_definitions_for_document(&document); | ||
| let old_document = self.documents.remove(&uri_id); | ||
|
|
||
| self.invalidate(old_document.as_ref(), Some(&other)); |
There was a problem hiding this comment.
It might be worth adding a fast path for the initial indexing on boot (which can trigger no invalidation and no removal of data).
Maybe a boolean flag for skipping invalidation.
| && let Some(nesting_id) = name_ref.nesting() | ||
| && let Some(NameRef::Resolved(resolved)) = self.names.get(nesting_id) |
There was a problem hiding this comment.
Can you clarify that document change this is accounting for? I'm having a hard time understanding it.
A constant reference was changed and we're enqueuing invalidation for the reference's nesting declaration.
There was a problem hiding this comment.
This is for
class Foo
include Bar # constant reference, when added we invalidate Foo entirely for now
endI've added comments for it.
rust/rubydex/src/model/graph.rs
Outdated
|
|
||
| self.declarations.remove(&decl_id); | ||
| } else { | ||
| // Ancestor-stale mode |
There was a problem hiding this comment.
Added more comments. Basically, it's triggered in
class Foo
include Bar # this is added/removed
endSo we simply change ancestors/descendents update in this branch.
| } | ||
| } | ||
|
|
||
| self.declarations.remove(&decl_id); |
There was a problem hiding this comment.
This is also doing data removal. Maybe this is fine, but I'm calling it out because the method documentation mentions a separation between invalidation and removal.
There was a problem hiding this comment.
I currently treat declaration removal as invalidation, kinda similar to unresolving a name. We remove (unresolve) the declaration here if we found it has no underlying definitions anymore.
The underlying materials (definitions, constant references, names...etc.) are only removed in remove_document_data.
| return; | ||
| }; | ||
|
|
||
| // Remove self from each ancestor's descendant set |
There was a problem hiding this comment.
I could be misunderstanding and maybe this was an existing bug, but removing self is not enough. The entire ancestor chain of self must be removed from descendants. However, we should absolutely not try to perform this removal because there are module deduping rules that you cannot possibly account for with a removal.
Whenever a declaration gets invalidated, we always need to invalidate the ancestors of all descendants. In both branches of this method.
There was a problem hiding this comment.
Both paths will update the ancestors. I've updated the document to make it more clear: invalidate_declaration either "remove/rebuild" or "update" a declaration. In both paths we update ancestors.
This also means there are optimization opportunities in both paths we can do later, which I also included in comments.
de13a32 to
d560ba6
Compare
d560ba6 to
6862eca
Compare
|
If we adopt #654, we should carry the memoized |
6862eca to
e37a74a
Compare
Introduces a worklist-based invalidation engine that cascades changes through the graph when documents are updated or deleted. Uses ChildName/NestedName edges from the name_dependents index to propagate invalidation with two distinct modes: - Structural cascade (UnresolveName): declaration removed or scope broken - Ancestor cascade (UnresolveReferences): ancestor chain changed Replaces the has_unresolved_dependency runtime check with explicit invalidation variants determined at queue time.
e37a74a to
9ae2496
Compare
Replaces the old
remove_definitions_for_document+invalidate_ancestor_chainsapproach with a targeted invalidation engine. When a file is updated or deleted, the engine traces through thename_dependentsreverse index to invalidate only the affected declarations, names, and references — instead of requiring a full graph rebuild.How it works
consume_document_changes()(renamed fromupdate()) anddelete_document()run a three-step pipeline:invalidate— read-only scan that seeds a worklist from old/new definitions and references, building apending_detachmentsside table for definitions that need to be detached from their declarationsremove_document_data— cleans up phase 1 data (definitions, references, names, strings) from mapsextend— merges new content and queues work items for the resolverThe resolver still does
clear_declarations+ full rebuild. Wiring it to drainpending_workincrementally is a follow-up.Invalidation worklist
The worklist processes three item types:
Declaration— two modes:class Foo::Barsurvives even ifFoochanges from a module to an alias).Name— structural dependency broken (name's nesting or parent scope removed). Unresolves the name and cascades to all dependents.References— ancestor context changed, but the name itself is still valid. Needed for mixin-related invalidation:Cascade differentiation
The
name_dependentsreverse index distinguishesChildName(compact syntaxFoo::Bar) fromNestedName(nested syntaxmodule Foo; class Bar; end; end):ChildNameandNestedName→NameChildName→Name(resolves through parent),NestedName→References(only references need rechecking)